//
// Created by 游钐栗 on 2022/10/9.
//

#ifndef MEDIATOOLS_ENCODEWND_H
#define MEDIATOOLS_ENCODEWND_H

#include <QWidget>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cinttypes>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#include <libavutil/opt.h>
#include <libavutil/time.h>
#include <libavutil/imgutils.h>
}


QT_BEGIN_NAMESPACE
namespace Ui { class EncodeWnd; }
QT_END_NAMESPACE

class EncodeWnd : public QWidget {
Q_OBJECT

public:
    explicit EncodeWnd(QWidget *parent = nullptr);

    ~EncodeWnd() override;

private slots:
    void encode_audio_Button_clicked();
    void encode_video_Button_clicked();

private:
    Ui::EncodeWnd *ui;

    /**
     * 解析pcm裸流的采样率、声道、编码质量，生成aac格式需要的ADTS header
     * @param ctx 编码器上下文
     * @param adts_header adts header
     * @param aac_length aac文件大小
     */
    static void get_adts_header(AVCodecContext *ctx, uint8_t *adts_header, int aac_length);

    /**
     * 检测该编码器是否支持该采样格式
     * @param codec
     * @param sample_fmt
     * @return 支持该采样率返回1, 否则返回0
     */
    static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt);

    /**
     * 检测该编码器是否支持该采样率
     * @param codec
     * @param sample_rate
     * @return 支持返回1, 否则返回0
     */
    static int check_sample_rate(const AVCodec *codec, const int sample_rate);

    /**
     * 检测该编码器是否支持声道布局
     * @param codec
     * @param channel_layout
     * @return 支持返回1, 否则返回0
     */
    static int check_channel_layout(const AVCodec *codec, const uint64_t channel_layout);

    /**
     * 将pcm音频由实际的packed格式的f32le转换为ffmpeg支持的planar格式——AV_SAMPLE_FMT_FLTP
     * @param f32le packed排列的浮点数
     * @param fltp planar排列的浮点数
     * @param nb_samples
     */
    static void f32le_convert_to_fltp(float *f32le, float *fltp, int nb_samples);

    /**
     * 音频编码函数
     * @param ctx
     * @param frame
     * @param pkt
     * @param output
     * @param pts
     * @return
     */
    static int encode_audio(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *output, uint64_t pts);

    /**
     * 视频编码函数
     * @param enc_ctx
     * @param frame
     * @param pkt
     * @param outfile
     * @return
     */
    static int encode_video(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt, FILE *outfile);

    /**
     * 将pcm编码成aac的主要实现
     * @param q_filename
     */
    int pcm_convert_to_aac(QString q_filename);

    /**
     * 将yuv编码成H264/265的主要实现
     * @param q_filename
     * @return
     */
    int yuv_convert_to_h264(QString q_filename);

    /**
    * 用户自定义的信号槽
    */
    void custom_signalslot();

    int64_t get_milsec();

};


#endif
